package com.struc.td;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.Array;

public class UnitTester {
	private Main main;
	private Game game;
	private MainMenu mainMenu;
	private int curTest;
	private Array<Waypoint> wayPointTests;
	private SpriteBatch testSB;
	private Player testPlayer;
	/* This is our unit tester class. It will run
	 * most methods in the application and make sure
	 * that the result is correct. If it is wrong it
	 * will print that it failed, if it is good nothing
	 * will happen. 
	 */
	public UnitTester(Main main) {
		wayPointTests = new Array<Waypoint>();
		this.main = main;
		curTest = 0;
		game = ((Game) main.getState(2));
		mainMenu = ((MainMenu) main.getState(1));
		testSB = new SpriteBatch();
	}
	public void run() {
		testSB.begin();
		try {
			testPlayer = new Player();
			testPlayer.setGold(1000);
			testPlayer.incGold(10000);
			testPlayer.incGold(-1000);
			if (testPlayer.getGold() != 10000) {
				Gdx.app.log("Unit test", "Making a player failed.");	
			}
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Making a player failed.");
		}
		try {
			Waypoint w = new Waypoint(100,100);
			wayPointTests.add(new Waypoint(0,-120));
			wayPointTests.add(w);
			if (!(w.getX() == 100 && w.getY() == 100)) {
				Gdx.app.log("Unit test", "Making waypoint failed");
			}
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Making waypoint failed");
		}
		try {
			EnemyArmored e = new EnemyArmored(1,0,wayPointTests);
			e.setTimer(400);
			e.update();
			e.render(testSB);
			e.renderHp(testSB);
			e.renderInfo(testSB);
			e.getExitInfoRect();
			e.getBounds();
			e.getInfoBounds();
			if (e.getDead() == true || e.reachedGoal() == true || e.getValue() != (2^(1+3))+1)
				Gdx.app.log("Unit test", "Making armored enemy failed");
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Making armored enemy failed");
			System.out.println(e);
		}
		try {
			EnemyNormal e = new EnemyNormal(1,0,wayPointTests);
			e.setTimer(400);
			e.update();
			e.render(testSB);
			e.renderHp(testSB);
			e.renderInfo(testSB);
			e.getExitInfoRect();
			e.getBounds();
			e.getInfoBounds();
			if (e.getDead() == true || e.reachedGoal() == true || e.getValue() != (2^(1+3))+1)
				Gdx.app.log("Unit test", "Making armored enemy failed");
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Making normal enemy failed");
		}
		try {
			EnemySpeed e = new EnemySpeed(1,0,wayPointTests);
			e.setTimer(400);
			e.update();
			e.render(testSB);
			e.renderHp(testSB);
			e.renderInfo(testSB);
			e.getExitInfoRect();
			e.getBounds();
			e.getInfoBounds();
			if (e.getDead() == true || e.reachedGoal() == true || e.getValue() != (2^(1+3))+1)
				Gdx.app.log("Unit test", "Making armored enemy failed");
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Making speed enemy failed");
		}
		try {
			Level l = new Level(1);
			if (!(Level.waypoints.size == 14 && l.getLevel().size == 5 && l.getLevel().get(0) instanceof EnemyNormal)) {
				Gdx.app.log("Unit test", "Making level failed");				
			}
			l = new Level(2);
			if (!(Level.waypoints.size == 14 && l.getLevel().size == 5 && l.getLevel().get(0) instanceof EnemyArmored)) {
				Gdx.app.log("Unit test", "Making level failed");				
			}
			l = new Level(3);
			if (!(Level.waypoints.size == 14 && l.getLevel().size == 5 && l.getLevel().get(0) instanceof EnemySpeed)) {
				Gdx.app.log("Unit test", "Making level failed");				
			}
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Making level failed");
		}
		try {
			TowerDamage td = new TowerDamage(100,100,game);
			td.update();
			td.render(testSB);
			td.renderInfo(testSB);
			td.renderRange(testSB);
			testPlayer.setGold(1000);
			td.upgradeRange(testPlayer);
			td.upgradeSpecial(testPlayer);
			if (td.getBounds().getX() != 100 || td.getBounds().getY() != 100 || td.getSold() == true)
				Gdx.app.log("Unit test", "Making damage tower failed");
			testPlayer.setGold(0);
			td.sell(testPlayer);
			if (!(testPlayer.getGold() > 0) || td.getSold() == false)
				Gdx.app.log("Unit test", "Making damage tower failed");
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Making damage tower failed");
		}
		try {
			TowerSlow ts = new TowerSlow(100,100,game);
			ts.update();
			ts.render(testSB);
			ts.renderInfo(testSB);
			ts.renderRange(testSB);
			testPlayer.setGold(1000);
			ts.upgradeRange(testPlayer);
			ts.upgradeSpecial(testPlayer);
			if (ts.getBounds().getX() != 100 || ts.getBounds().getY() != 100 || ts.getSold() == true)
				Gdx.app.log("Unit test", "Making slow tower failed");
			testPlayer.setGold(0);
			ts.sell(testPlayer);
			if (!(testPlayer.getGold() > 0) || ts.getSold() == false)
				Gdx.app.log("Unit test", "Making slow tower failed");
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Making slow tower failed");
		}
		try {
			ProjectileDamage pd = new ProjectileDamage(new EnemyNormal(100,100,Level.waypoints),100,100,4);
			pd.setTimer(50);
			pd.update();
			pd.render(testSB);
			if (pd.getDmg() != 4 || pd.isDead() == true) {
				Gdx.app.log("Unit test", "Making damage projectile failed");	
			}
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Making damage projectile failed");
		}
		try {
			ProjectileSlow ps = new ProjectileSlow(new EnemyNormal(100,100,Level.waypoints),100,100,4);
			ps.setTimer(50);
			ps.update();
			ps.render(testSB);
			if (ps.isDead() == true || ps.getSlow() != 4) {
				Gdx.app.log("Unit test", "Making slow projectile failed");	
			}
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Making slow projectile failed");
		}
		try {
			ProjectileDamage pd = new ProjectileDamage(new EnemyNormal(100,100,Level.waypoints),100,100,400);
			EnemyArmored ea = new EnemyArmored(1,0,wayPointTests);
			EnemyNormal en = new EnemyNormal(1,0,wayPointTests);
			EnemySpeed es = new EnemySpeed(1,0,wayPointTests);
			ea.gotHit(pd);
			if (ea.getDead() != true)
				Gdx.app.log("Unit test", "Armored Enemy hit by damage projectile failed.");	
			en.gotHit(pd);
			if (en.getDead() != true)
				Gdx.app.log("Unit test", "Normal Enemy hit by damage projectile failed.");
			es.gotHit(pd);
			if (es.getDead() != true)
				Gdx.app.log("Unit test", "Speed Enemy hit by damage projectile failed.");
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Enemy hit by damage projectile failed.");
		}
		try {
			ProjectileSlow p = new ProjectileSlow(new EnemyNormal(100,100,Level.waypoints),100,100,0.4f);
			
			EnemyArmored ea = new EnemyArmored(1,0,wayPointTests);
			EnemyNormal en = new EnemyNormal(1,0,wayPointTests);
			EnemySpeed es = new EnemySpeed(1,0,wayPointTests);
			ea.gotHit(p);
			if (ea.getDead() == true || ea.currentSpeed() != 0.4f)
				Gdx.app.log("Unit test", "Armored Enemy hit by slow projectile failed.");	
			en.gotHit(p);
			if (en.getDead() == true || ea.currentSpeed() != 0.4f)
				Gdx.app.log("Unit test", "Normal Enemy hit by slow projectile failed.");
			es.gotHit(p);
			if (es.getDead() == true || ea.currentSpeed() != 0.4f)
				Gdx.app.log("Unit test", "Speed Enemy hit by slow projectile failed.");
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Enemy hit by slow projectile failed.");
		}
		try {
			TowerSpace sp = new TowerSpace(100,100);
			sp.render(testSB);
			sp.renderInfo(testSB);
			sp.renderSelected(testSB);
			if (sp.getBounds().getX() != 100 || sp.getBounds().getY() != 100) {
				Gdx.app.log("Unit test", "Tower Space positioning failed.");
			}
			sp.getInfoBounds();
			sp.getDamageTowerRect();
			sp.getSlowTowerRect();
			sp.getExitInfoRect();
			
		} catch (Exception e) {
			Gdx.app.log("Unit test", "Tower Space failed.");
		}
		try {
			
		} catch (Exception e) {
			
		}
		testSB.end();
	}
}
